home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODF-Interest Archive / July 96 / problems with arc shapes < prev    next >
Encoding:
Internet Message Format  |  1996-08-01  |  4.4 KB  |  [TEXT/ttxt]

  1. Subject:     problems with arc shapes
  2. Sent:        7/29/96 8:53 AM
  3. Received:    7/29/96 9:01 AM
  4. From:        Uwe Schoeneberg, odf@softgene.spacenet.de
  5. Reply-To:    ODF Interest, ODF-Interest@CILabs.ORG
  6. To:          OpenDoc Development Framework Discussion List, ODF-Interest@CILabs.
  7.  
  8. I guess this a bug in how ODF handles arcs:
  9.  
  10. I was playing around with arc shapes and I thought
  11.  
  12.         FW_CArcShape::RenderArc(gc, rect,
  13.                                 startAngle, arcAngle,
  14.                                 FW_kFill, fFillInk, fFillStyle);
  15.  
  16. should have the same result on the screen as
  17.  
  18.         FW_CAcquiredODShape aqSegmentShape =
  19.                 ::FW_CreateArcODShape(ev, rect, startAngle, arcAngle);
  20.  
  21.         FW_CRegionShape::RenderRegion(gc, aqSegmentShape,
  22.                                       FW_kFill, fFillInk, fFillStyle);
  23.  
  24. but I was wrong for startAngle == 90, 180, 270 and arcAngle == 45;
  25.  
  26. During tracing from FW_CreateArcODShape into the ODFLibrary I found that,
  27. in SLRegion.cpp, method FW_CreateArcRegion, the polygon wasn't closed. So I
  28. changed
  29.  
  30.         ::MoveTo(pt[0].h, pt[0].v);
  31.         for (short i = 1; i < 6; i ++)
  32.             ::LineTo(pt[i].h, pt[i].v);
  33.  
  34. to
  35.  
  36.         ::MoveTo(pt[5].h, pt[5].v);
  37.         for (short i = 0; i < 6; i ++)
  38.             ::LineTo(pt[i].h, pt[i].v);
  39.  
  40.  
  41. In addition, PrivCalcArcPoints (in PRGrUtil.cpp) does not seem to always
  42. return the right values in arcPoint. I would like to discuss my solution
  43. for PrivCalcArcPoints with [KVV]:
  44.  
  45. void SL_API FW_PrivCalcArcPoints(const FW_CPlatformRect& rect,
  46.                                  short angle,
  47.                                  FW_CPlatformPoint& arcPoint)
  48. {
  49.    FW_Fixed fxRad = (FW_IntToFixed(angle) * FW_kFixedPI) / FW_IntToFixed(180);
  50.  
  51.    FW_PlatformCoordinate middleX = (rect.right + rect.left) / 2;
  52.    FW_PlatformCoordinate middleY = (rect.bottom + rect.top) / 2;
  53. //                              was rect.right + rect.left !!!
  54.  
  55.    const FW_Fixed halfX = FW_IntToFixed((rect.right - rect.left) / 2);
  56.    const FW_Fixed halfY = FW_IntToFixed((rect.bottom - rect.top) / 2);
  57.  
  58.    short shortX = FW_FixedToInt(halfX * FW_Sin(fxRad));
  59.    short shortY = -FW_FixedToInt(halfY * FW_Cos(fxRad));
  60.  
  61.    arcPoint.Set(shortX + middleX, shortY + middleY);
  62. }
  63.  
  64. This way, FW_PrivCalcArcPoints gives a better approximation of an ellipse
  65. and hence FW_CreateArcRegion be changed to the following (Mac code only):
  66.  
  67. ODRgnHandle SL_API FW_CreateArcRegion(const FW_SRect& rect,
  68.                                       short startAngle, short arcAngle)
  69. {
  70.     // No try block necessary - Do not throw
  71.     FW_CPlatformRect plfmRect = rect;
  72.  
  73. #ifdef FW_BUILD_MAC
  74.  
  75.     if (startAngle >= 360)
  76.         startAngle = startAngle % 360;
  77.     else if (startAngle < 0)
  78.         startAngle = (startAngle % 360) + 360;
  79.  
  80.     if (arcAngle > 360)
  81.         arcAngle = arcAngle % 360;
  82.  
  83.     if (arcAngle == 0)
  84.         arcAngle = 360;
  85.     else if (arcAngle < 0)
  86.         arcAngle = (arcAngle % 360) + 360;
  87.  
  88.     const ODUShort anglePerSegment = 5;
  89.     const ODUShort maxSegments = (360 / anglePerSegment) +1;
  90.     ODUShort numSegments = arcAngle / anglePerSegment;
  91.  
  92.     ODUShort angle = startAngle;
  93.     FW_CPlatformPoint pt[maxSegments];          //  pt[numSegments +1]
  94.     for (ODUShort i = 0; i <= numSegments; i++) // we create numSegments +1
  95. points
  96.     {
  97.         angle = startAngle + arcAngle * i / numSegments;
  98.         FW_PrivCalcArcPoints(plfmRect, angle, pt[i]);
  99.     }
  100.  
  101.     // Create a polygon region
  102.     GrafPtr savePort = ::PrivMacOpenRegion();
  103.  
  104.     FW_CPlatformPoint center((plfmRect.left + plfmRect.right) / 2,
  105.                              (plfmRect.top + plfmRect.bottom) / 2);
  106.     ::MoveTo(center.h, center.v);
  107.     for(ODUShort j = 0; j <= numSegments; j++) // we have numSegments +1 points
  108.         ::LineTo(pt[j].h, pt[j].v);
  109.     ::LineTo(center.h, center.v);
  110.  
  111.     ODRgnHandle hArcRegion = ::PrivMacCloseRegion(savePort);
  112.  
  113.     // Return the result
  114.     return hArcRegion;
  115. #endif
  116.  
  117. #ifdef FW_BUILD_WIN
  118.  
  119. // Windows code here
  120.  
  121. #endif
  122. }
  123.  
  124. I also found out that, in method FW_PrivRenderArc, for a renderVerb ==
  125. FW_kFrame the result on the screen is different for Windows and MacOS as
  126. FrameRgn frames the whole wedge with a region that comes out of
  127. ::FW_CreateArcRegion whereas FrameArc just draws an arc.
  128.  
  129. Uwe Schoeneberg
  130.  
  131.  
  132. -----------------------------------------------------------------------------
  133. Soft Gene GmbH
  134. Offenbacher Str. 5
  135. 14 197 Berlin                                        Tel:    +49-30 841 71 50
  136. Germany                                              Fax:    +49-30 821 97 64
  137.  
  138.  
  139.  
  140.  
  141.  
  142.